package net.cz.wc.parser;

import java.io.File;
import java.sql.Connection;
import java.util.Scanner;

import net.cz.wc.main.Context;
import net.cz.wc.olddto.GCMetricsDTO;
import net.cz.wc.olddto.ThreeGCFields;
import net.cz.wc.output.ConsoleOutput;
import net.cz.wc.util.DataUtils;

/**
 * Parser for a garbage collection log file for a HotSpot JVM
 * @author carloszuluaga
 *
 */
public class HotSpotParser{
	
	public void parse(File file, Connection conn) throws Exception {
		
		ConsoleOutput.printPipedGCHeader();
		
		Scanner scan = null;
		try {
			scan = new Scanner(file);
			int lineNumber = 0;
			int youngGcs = 0;
			int fullGcs = 0;
			
			while (scan.hasNextLine()) {
				lineNumber++;
				String line = scan.nextLine();
				if ((line.indexOf("[GC") > 0)) {
					processGC(line, scan);
					youngGcs++;
				}
				
				if ((line.indexOf("[Full GC") > 0)) {
					processFullGC(line, scan);
					fullGcs++;
				}
			}
			
			Context.getContext().print("");
			Context.getContext().print(lineNumber + " processed lines.");
			Context.getContext().print(youngGcs + " young collections");
			Context.getContext().print(fullGcs + " full collections");
			Context.getContext().print((youngGcs + fullGcs) + " total collections");
		} catch (Exception ee) {
			ee.printStackTrace();
		} finally {
			if (scan != null) {
				scan.close();
			}
		}
	}
	
	public static final String FULL_GC = "FULL";
	public static final String MINOR_GC = "MINOR";
	
	/**
	 * Process a full GC event
	 * @param currLine line where the GC started
	 * @param currScanner scanner for the log file
	 */
	private final void processFullGC (String currLine, Scanner currScanner) {
		GCMetricsDTO gcMetrics = new GCMetricsDTO();
		gcMetrics.setGcType(FULL_GC);
		gcMetrics.setTimestamp(currLine.substring(1,19));

		int currIndex = currLine.indexOf("[ParOldGen");
		currIndex = currLine.indexOf(")]", currIndex);
		
		String stringData = currLine.substring(currIndex + 3, currLine.indexOf(")", currIndex + 3) + 1);
		ThreeGCFields fields = DataUtils.extractThreeGCFields(stringData);

		gcMetrics.setUsedHeap(fields.getCurrentUsage());
		gcMetrics.setHeapAfterGC(fields.getUsageAfterGC());
		gcMetrics.setTotalHeap(fields.getTotalSize());
		
		ConsoleOutput.printOnlyHeapMetrics(gcMetrics);
	}
	
	/**
	 * Process a GC event
	 * @param currLine line where the GC started
	 * @param currScanner scanner for the log file
	 */
	private final void processGC (String currLine, Scanner currScanner) {
		GCMetricsDTO gcMetrics = new GCMetricsDTO();
		gcMetrics.setGcType(MINOR_GC);
		gcMetrics.setTimestamp(currLine.substring(1,19));
		
		currScanner.nextLine();
		String gcLine = currScanner.nextLine();
		
		int currIndex = gcLine.indexOf(")]");
		
		String stringData = gcLine.substring(currIndex + 3, gcLine.indexOf(")", currIndex + 3) + 1);
		ThreeGCFields fields = DataUtils.extractThreeGCFields(stringData);
		
		gcMetrics.setUsedHeap(fields.getCurrentUsage());
		gcMetrics.setHeapAfterGC(fields.getUsageAfterGC());
		gcMetrics.setTotalHeap(fields.getTotalSize());
		
		ConsoleOutput.printOnlyHeapMetrics(gcMetrics);
	}
}
